package com.resource.configuration.http;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;

/**
 * 添加http请求拦截器
 *
 * @author Tao.yu
 * @version v3.0
 * @date 2019/12/9 17:48
 **/
@Slf4j
@Lazy(false)
@Component
public class HttpClientUtils {

	private static RestTemplate restTemplate;

	@Resource
	private RestTemplateBuilder builder;

	@Autowired
	public void setRestTemplate() {
		HttpClientUtils.restTemplate = restTemplate();
	}

	@Bean
	public RestTemplate restTemplate() {
		RestTemplate build = builder.build();
//		SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
//		requestFactory.setReadTimeout(5000);
//		requestFactory.setConnectTimeout(5000);
//		build.setRequestFactory(requestFactory);
		build.setRequestFactory(clientHttpRequestFactory());
		List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
		/* 设置请求头接口开放 */
		// interceptors.add(new HeadClientHttpRequestInterceptor());
		build.getMessageConverters().add(new CustomMappingJackson2HttpMessageConverter());
		interceptors.add(new TrackLogClientHttpRequestInterceptor());
		build.setInterceptors(interceptors);
		return build;
	}


	private HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
		try {
			HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
					return true;
				}
			}).build();
			httpClientBuilder.setSSLContext(sslContext);
			HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
			SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
					hostnameVerifier);
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.getSocketFactory())
					// 注册http和https请求
					.register("https", sslConnectionSocketFactory).build();
			// 开始设置连接池
			PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);
			// 最大连接数500
			poolingHttpClientConnectionManager.setMaxTotal(500);
			// 同路由并发数100
			poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
			httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
			// 重试次数
			httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));
			HttpClient httpClient = httpClientBuilder.build();
			// httpClient连接配置
			HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
					httpClient);
			// 连接超时
			clientHttpRequestFactory.setConnectTimeout(20000);
			// 数据读取超时时间
			clientHttpRequestFactory.setReadTimeout(30000);
			// 连接不够用的等待时间
			clientHttpRequestFactory.setConnectionRequestTimeout(20000);
			return clientHttpRequestFactory;
		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
			log.error("初始化HTTP连接池出错", e);
		}
		return null;
	}



	@PostConstruct
	public static RestTemplate getClient() {
		return restTemplate;
	}

}
